package graphics.tools;

import graphics.shapes.Ball;
import graphics.shapes.Rod;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.swing.JOptionPane;

import com.sun.j3d.utils.picking.PickCanvas;
import com.sun.j3d.utils.picking.PickResult;
import com.sun.j3d.utils.picking.PickTool;

/**
 * For making selections of objects in the 3D-universe by click.
 * 
 * @author: Eirik Vigeland
 * @version: %I%, %G%
 */
public class PickObject extends PickCanvas implements MouseListener {

	/**
	 * Constructor setting up the extended PickCanvas and mode of picking
	 * 
	 * @param cv
	 *            Canvas3D, the canvas to be picked from.
	 * @param bg
	 *            BranchGroup from where to pick.
	 */
	public PickObject(Canvas3D cv, BranchGroup bg) {
		super(cv, bg);
		this.setMode(PickTool.GEOMETRY);
	}

	/**
	 * Controls the output of the selection made and passes the argument to the
	 * proper controller for the selected object
	 * 
	 * @param result
	 *            Result of the pick
	 * @param button
	 *            The pressed button
	 */
	private void selectionControl(PickResult result, int button) {
		Object node = result.getObject().getParent().getParent().getParent();
		if (node instanceof Ball) {
			ballControl(node, button);
		} else if (node instanceof Rod) {
			rodControl(node, button);
		}
	}

	/**
	 * 
	 * Controls the result of picked object if the selection is a rod
	 * 
	 * @param node
	 *            A Rod
	 * @param button
	 *            The pressed button
	 */
	private void rodControl(Object node, int button) {
		Rod selectedRod = (Rod) node;
		if (button == MouseEvent.BUTTON1) {
			if (selectedRod.isTransparent()) {
				node = selectedRod.getParent();
				if (node instanceof Ball) {
					Ball selectedBall = (Ball) node;
					selectedBall.attachRod(selectedRod);
					selectedBall.hideRods();
				}
			} else if (selectedRod.getBall() != null) {
				selectedRod.showBall();
			} else {
				selectedRod.addBall(getBranchGroup());
			}
		} else {
			if (selectedRod.isTransparent()) {
				JOptionPane.showMessageDialog(null,
						"This rod is not attached yet!", "Not attached!",
						JOptionPane.WARNING_MESSAGE);
			} else if (getBranchGroup().indexOfChild(selectedRod.getBall()) != -1) {
				JOptionPane.showMessageDialog(null,
						"Can not remove a rod that has items attached to it!",
						"Can not remove!", JOptionPane.WARNING_MESSAGE);
			} else {
				selectedRod.getParentNode().removeRod(selectedRod);
			}

		}
	}

	/**
	 * Controls the result of the picked object if the selection is a
	 * ball/sphere
	 * 
	 * @param node
	 *            A Ball
	 * @param button
	 *            The pressed button
	 */
	private void ballControl(Object node, int button) {
		Ball selectedBall = (Ball) node;
		if (button == MouseEvent.BUTTON1) {
			if (selectedBall.isTransparent()) {
				Rod selectedRod = selectedBall.getParentRod();
				selectedRod.attachBall();

			} else {
				selectedBall.showRods();
			}
		} else {
			if (selectedBall.isRootNode()) {
				JOptionPane.showMessageDialog(null, "Cannot remove the root!",
						"Cannot remove!", JOptionPane.WARNING_MESSAGE);
			} else if (selectedBall.hasChildren()) {
				JOptionPane
						.showMessageDialog(
								null,
								"This node has children attached to it, please remove the children first!",
								"Has children attached!",
								JOptionPane.WARNING_MESSAGE);
			} else if (selectedBall.isTransparent()) {
				JOptionPane.showMessageDialog(null,
						"This node is not yet attached!", "Not attached!",
						JOptionPane.WARNING_MESSAGE);
			} else {
				selectedBall.getParentRod().removeBall(selectedBall);
			}
		}
	}

	/**
	 * For the event of a Mouse Pressed, find the item click (if possible) and
	 * continue pursue to the selectionControl
	 * 
	 * @param e
	 *            The event of the mouse.
	 */
	@SuppressWarnings("static-access")
	@Override
	public void mousePressed(MouseEvent e) {
		if (e.getButton() == e.BUTTON1 || e.getButton() == e.BUTTON3) {
			this.setShapeLocation(e);
			PickResult result = this.pickClosest();
			if (result != null) {
				selectionControl(result, e.getButton());
			}
		}
	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
	}

}
